一、最難堪的效能缺陷單:兇手是自己
先講一個業界每週都在上演的故事。你照 Day 18 的方法交出漂亮的判讀:「40 VU 後 rps 打平、timeout 上升,嫌疑在應用層容量。」RD 認真查了半天:伺服器 CPU 才兩成、連線池空著、慢查詢 log 乾乾淨淨——什麼都沒滿。最後有人繞到你座位後面看了一眼:你的筆電風扇狂轉,CPU 100%,還開著三十個瀏覽器分頁。打平的不是系統的吞吐量,是你筆電的。一整輪測試作廢事小,往後你的每份報告都會被多問一句「這次施壓機沒問題吧」——信用比數據貴。
這個故事的教訓值得寫在牆上:效能測試是用一個系統去量另一個系統,而量測工具自己也是一個會飽和的系統。從你的筆電到受測系統之間是一條量測鏈——施壓機、網路、快取、系統本身——四站有一站先到極限,你量到的就是那一站。Day 18 圖 2 的第四個嫌疑人「施壓端自己」,今天連同它的三個同夥一起處理。

圖 1:量測鏈上每一站都可能先飽和——先到極限的那一站,就是你實際量到的東西
二、陷阱一與二:施壓機先倒下,連線成本失真
陷阱一:施壓機先到極限。症狀認得出來就成功一半:rps 上不去但伺服器很閒(RD 說「我這邊沒事啊」);k6 輸出出現 dropped_iterations——這是 k6 在明白告訴你「我來不及產生你要的負載」;作業系統丟出 too many open files;或者 Day 18 學過的 http_req_blocked 肥大——請求在你自己機器裡排隊等連線。確認方法樸素到不好意思:跑測試時,開著工作管理員(或 top)看自己的機器。施壓機 CPU 過了七成,這一輪的數字就開始摻水。
排除方式按順序試:關掉吃資源的程式(瀏覽器分頁是慣犯)、降 VU 或簡化腳本、拉高作業系統的檔案描述符上限(請 Claude Code 依你的作業系統給指令)。都不夠?那就是單機的極限到了——一台普通筆電跑輕量 API 腳本,幾百個 VU 通常沒問題,上千就要警覺;需要更大的量,該從雲端打(Day 25 的主題)。
陷阱二:連線成本失真。Day 18 解剖過一個請求:connecting 與 tls 交握是進門前的成本。k6 預設每個 VU 重用連線(keep-alive),這模擬的是「回頭客」——瀏覽器開著、連線熱著。但有兩種失真:一是你不小心關了重用(或每次迭代都建新連線),connecting+tls 佔比暴增,測出來的是交握成本不是系統處理能力,數字假慢;二是反過來,你想模擬的明明是「開賣那一秒湧進來的一萬個新使用者」——每個人都是冷連線——卻用預設的熱連線去測,數字假快。連線模式沒有對錯,只有和情境符不符——選哪種都行,但要是有意識的選擇,而且寫進測試筆記。DNS 同理:k6 有 DNS 快取,第一次解析之後就不再是成本;只有當你看到測試開頭一小段 blocked 特別高,才需要想起它。
三、陷阱三與四:測到快取,撞到頻寬
陷阱三:測到快取,而非處理能力。Day 17 講過環境端的冷熱,今天講更陰險的版本——你的測試設計讓快取命中率高得不真實。經典成因正是 Day 9 的老朋友:全員用同一筆測試資料。第一個請求之後,那筆資料躺進快取,後面九千九百九十九個請求全是快取在回話,資料庫全程睡覺。另一個變形:受測路徑前面架著 CDN 或反向代理,你壓的 GET 全被它接走了,流量根本沒進你的系統。
症狀有三個指紋:快得不合理(比 Day 16 訂的目標好十倍——先別高興);p50 極快但 p99 慢很多——命中與未命中的雙峰,Day 18 說的「差距懸殊必有故事」就是這個故事;VU 一路加、回應時間紋風不動——像在壓一面牆,因為你真的在壓一面牆(快取牆)。確認與排除:資料參數化再跑一輪對比(Day 9 的功課直接回收);檢查回應 header 有沒有 X-Cache: HIT、Age、cf-cache-status 這類快取指紋。要不要把快取算進測試?都可以——生產路徑本來就有快取,含著測也是真實;重點是你知道自己在測哪一種,而且報告裡寫明。
陷阱四:辦公室網路的頻寬天花板。這個陷阱可以用小學數學抓到:100 Mbps 的辦公室網路約等於 12.5 MB/s;如果平均回應 50KB,理論天花板就是 250 rps 上下——不管伺服器多強,你從這條線打,rps 就是過不去。症狀:receiving 肥大(Day 18 的分段再度出場)、rps 卡在一個和頻寬換算吻合的數字、以及同事開始抱怨網路變慢(這其實是 Day 6 壓測禮儀的問題了)。確認方法:k6 輸出裡有 data_received 的每秒速率,拿它對照你的網路頻寬,一除就見真章。排除:換個位置打(機房跳板機、雲端);經過 VPN 更要小心——加密隧道的損耗會讓天花板更低。「從哪裡打」和「打多少」一樣,是測試設計的一部分;不同施壓位置測出的數字不可混著比較——這是 Day 17 四同原則的第五個同。

四個陷阱認完,把順序固定下來:先審證據,再開推理。Day 18 的三條線索很好用,但前提是線索本身沒被污染——可信度四問(施壓機喘了嗎、connecting+tls 佔比正常嗎、快得合理嗎、離頻寬天花板還遠嗎)走完全過,才輪到推理登場;任何一問卡住,先修正、再重測,而且一次只修一件事——修兩件以上,你就不知道是誰治好的。

圖 2:先審證據,再開推理——可信度四問全過,Day 18 的推理才有意義
四、動手做:親手讓證據說一次謊
練習一:污染對照實驗。公開站不能開大流量,所以我們反向操作——不是把負載加大到施壓機喘,而是讓施壓機先忙起來,用同樣的小流量看數字失真。這是完全安全又最有說服力的一課:
Prompt 1|施壓機污染對照實驗
請設計一個對照實驗,證明施壓機忙碌會污染測試數據:
第一輪:在乾淨狀態執行 k6 run --vus 3 --duration 60s pizza-api-test.js,
記下 http_req_duration 的 avg/p95 與 iterations。
第二輪:先啟動一個吃滿 CPU 的背景程序(請寫一個安全的、
60 秒後自動結束的忙碌迴圈,並告訴我怎麼手動停止它),
再跑一模一樣的測試。
最後把兩輪結果做成對照表,說明哪些指標被污染、為什麼——
伺服器全程沒有變,變的只有量尺。
預期看到的戲碼:第二輪的 p95 變差、iterations 變少——但 QuickPizza 的伺服器從頭到尾沒變。同一個系統、兩組數字,差別只在量尺自己的狀態——這就是「證據污染」四個字最直觀的長相。看過一次,以後別人報告裡「慢了 30%」你都會多問一句:施壓機當時什麼狀態?
練習二:連線重用的開關對比。把陷阱二親手做一遍,小流量完全合法:
Prompt 2|回頭客 vs 新客潮
請執行兩輪測試並比較分段指標:
第一輪(預設,模擬回頭客):k6 run --vus 2 --duration 30s pizza-api-test.js
第二輪(模擬全新使用者潮):同一腳本加上 --no-connection-reuse
對照兩輪的 http_req_connecting、http_req_tls_handshaking、
http_req_duration(avg 與 p95),計算 connecting+tls 佔 duration 的比例,
並回答:哪一輪適合模擬「開賣瞬間湧入的新使用者」?
哪一輪適合模擬「掛著網頁操作的老使用者」?
練習三:頻寬天花板的算術,加一次快取指紋檢查。不用真的把網路打滿(那是 Day 6 禁止的事),用算的就夠:
Prompt 3|天花板換算與快取指紋
1. 從剛才任一輪的 k6 輸出讀出 data_received 的每秒速率,
假設我的網路是 100 Mbps,換算:目前用掉了頻寬的百分之幾?
照這個平均回應大小,rps 的理論天花板大約是多少?
2. 寫一小段 k6 腳本對 QuickPizza 首頁發一個 GET,
印出回應中與快取相關的 headers(如 X-Cache、Age、cache-control 等),
並解釋:如果看到命中的指紋,代表我壓到的是誰?
五、注意事項:守住可信度的六個習慣

給 RD 的一句話:當 QA 在報告開頭寫「施壓機 CPU 全程三成、connecting+tls 佔比 2%、資料已參數化、頻寬用量一成」——這四句話是他先把自己查了一遍的證明,後面的數字值得你認真對待。反過來也幫他一把:借他一台機房裡的跳板機打流量,勝過他在筆電上重測十次。
六、觀念驗證:三個問題確認你有帶走今天的重點
• 「rps 上不去」有兩種劇本:受測系統飽和、施壓機飽和——各自的佐證長什麼樣?哪個 k6 警告直接指向後者?(第一、二節)
• 全員用同一筆測試資料會觸發哪個陷阱?症狀在 p50 與 p99 上是什麼長相?這和 Day 9 的哪個教訓是同一件事?(第三節)
• 100 Mbps 的網路、平均回應 50KB,rps 天花板大約多少?撞到天花板時,Day 18 的哪個分段指標會先肥起來?(第三節)
七、小結
效能測試是用一個系統去量另一個系統,所以「數字不可信」的第一嫌疑人永遠包括量尺自己。四個污染源——施壓機極限、連線成本失真、快取、頻寬天花板——各有指紋,也各有排除法;而順序比技巧重要:先審證據,再開推理,一次只修一件事。到今天,判讀三部曲完整了:Day 17 看尺歪不歪(環境)、Day 18 讀線索(推理)、Day 19 驗證據(污染)。數字可信了、推理有了,下一個問題很實際:滿螢幕的終端輸出,怎麼讓主管一眼看懂?Day 20,零安裝的視覺化。
附錄:測試結果可信度檢核清單(影印版)
—— 施壓端 ——
□ 1. 測試全程施壓機 CPU < 70%? 記憶體有餘?
□ 2. 輸出沒有 dropped_iterations 警告?
□ 3. http_req_blocked 佔比正常 (沒在自己機器裡排隊)?
—— 連線與網路 ——
□ 4. 連線模式 (重用/不重用) 和模擬情境一致, 且寫進筆記?
□ 5. connecting + tls 佔 duration 比例合理 (通常 < 10%)?
□ 6. data_received 速率離頻寬天花板還遠?
□ 7. 施壓位置寫明 (辦公室/VPN/機房)? 比較時同一位置?
—— 測的東西 ——
□ 8. 測試資料已參數化, 不是全員同一筆? (Day 9)
□ 9. 檢查過回應 header 的快取指紋? 含不含快取是有意識的?
□ 10. 快得不合理的數字, 追問過為什麼才往上報?